perm filename MGRAPH.PUB[HAL,HE] blob
sn#133593 filedate 1974-12-04 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00003 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 .gph:NEWSS GRAPH STRUCTURES
C00009 00003 .gaf: NEWSSS GRAPH STRUCTURES AND AFFIXMENT
C00012 ENDMK
C⊗;
.gph:NEWSS GRAPH STRUCTURES
Affixments are stored in both the compiler and the runtime by means of a
%4graph structure%* which is used to assure that variable values are consistently
updated. The actual algorithms used for this process are given in
{apref rgp}. Essentially, the runtime system keeps track of dependencies
between variables. If a variable value is changed, any variables
which depend on it are marked as "invalid". Then, whenever the value
of an "invalid" variable is needed, the runtime system will attempt
to recompute it from the dependency information. If this attempt fails
(as might happen if two "invalid" variables depend on each other) then
the current ("invalid") value is used as the best answer available.
.newsss EXPLICIT MODIFICATIONS TO THE GRAPH STRUCTURE
The dependency information principally consists of a list of arithmetic
expressions that may be used to calculate the new value of a variable,
together with a list of statements to execute whenever the variable is
changed. (In addition, the runtime keeps with each variable a
list of all other variables
whose values may depend upon that variable). Generally, this information will
be updated implicitly as part of the AFFIX and UNFIX statements. However,
AL does provide statements for updating the structure explicitly.
The principal statement employed for this purpose is the %4graph
assignment statement%*:
.UNFILL
<variable> <= <expression>
.REFILL
where "<=" may be read "is computed by". This construct causes
<expression> to be added to the list of calculators for <variable>.
Also, it causes the left hand side <variable> to be added to the
dependents list of any variables that may occur in the <expression>.
Thus,
.unfill
FRAME f1, f2;
TRANS t;
f1 <= t*f2;
.refill
says that f1 is computed by the expression "t*f2" and, hence, depends
on t and f2. Note that graph assignment is cumulative, so that
.unfill
a <= b*c;
a <= d+e;
.refill
would cause a to be marked invalid whenever b, c, d, or e is changed.
In such a case, it is undefined whether "b*c" or "d+e" would be used
to recompute a, assuming that all of the variables were valid when
the value of a is needed.
The statement
.UNFILL
<variable> <≠ <expression>
.REFILL
causes <expression> to be removed from the list of calculators and
makes the appropriate modifications to the dependency lists.
Similarly,
.UNFILL
<variable> <<= <expression>
.REFILL
replaces the current calculator list for <expression>. The statement
.UNFILL
<variable> <<= ;
.REFILL
would cause the calculator list to be set to null.
In addition to the calculator list, a list of %4updater%* routines is
associated with every variable. These routines are executed whenever
the variable value is changed. Initially, the list of updaters is
empty. However, the construct
.UNFILL
WHEN CHANGING <variable> ALSO DO <label>: <statement>;
.REFILL
will cause the statement to be added to the list of updaters for
the variable. The label is optional, but is necessary if the statement
is ever to be removed from the updater list. In <statement>, the
reserved words OLD and NEW may be used to refer to the old and new
values of var, respectively. For instance:
.UNFILL
WHEN CHANGING f2 ALSO DO foo: f1 ← NEW*(OLD → F1);
.REFILL
Updaters may be removed from the updater list by the statement
.UNFILL
WHEN CHANGING <variable> DONT DO <label>
.REFILL
For our above example, this would be
.UNFILL
WHEN CHANGING f2 DONT DO foo;
.REFILL
The form
.UNFILL
WHEN CHANGING <variable> ONLY DO <statement>;
.REFILL
replaces the updater list with one containing just <statement>, and
.UNFILL
WHEN CHANGING <variable> ONLY DO ;
.REFILL
clears the updater list completely. Since the affix structure makes
use of updater and calculator lists (see {sssref rgf}), careless use of the
replacement form is not advised.
One possible use for updater routines is tracing. For example,
.UNFILL
WHEN CHANGING v ALSO DO
WRITE("The value of V is now ",NEW);
.REFILL
One additional point that should be mentioned here is that the
updater routines for a variable are %4not%* called if the variable's
value is modified as a side effect of a change to some variable in
one of its calculators.
.gaf: NEWSSS GRAPH STRUCTURES AND AFFIXMENT
As mentioned in the previous section, the AFFIX & UNFIX statements
modify the graph structure. In fact, these statements may be
be defined in terms of their effects on graph structure.
Thus,
.UNFILL
AFFIX f1 TO f2 BY t1
.BULL
is equivalent to
t1 ← f2 → f1;
f1 <= t1 * f2;
WHEN CHANGING f1 ALSO DO yyy:t1 ← (f2 → NEW);
.refill
One additional effect of AFFIX is to cause the compiler's planning
model to be updated by the addition of a symbolic assertion:
.unfill
ASSERT FORM(AFFIXED, f1, f2, NONRIGIDLY, t1);
.REFILL
Such assertions are described more fully in {ssref asr}. Essentially,
all this one does is record the fact that the two frames have been affixed.
This information is used in calculating deproaches ({ssref dep}) and
by several other parts of the compiler, and is also available to the user.
Similarly,
.UNFILL
UNFIX f1 FROM f2;
.REFILL
is equivalent to
.UNFILL
f1 <≠ t1*f2;
WHEN CHANGING f1 DONT DO yyy;
DENY FORM(AFFIXED, f1, f2, ANYTHING, ANYTHING);
ASSERT FORM(WAS_AFFIXED, f1, f2);
.REFILL
The latter assertion
is used in calculation of default deproach points. A side-effect of
any assignment, like "f1#α←#<value>", is
.UNFILL
DENY FORM(WAS_AFFIXED, ANYTHING, f1);
DENY FORM(WAS_AFFIXED, f1, ANYTHING) .
.REFILL
Rigid affixments, such as
.UNFILL
AFFIX f1 TO f2 BY t1 RIGIDLY
.REFILL
are equivalent to
.UNFILL
t1 ← f2 → f1;
f1 <= t1 * f2;
f2 <= INVERSE(t1) * f1 .
ASSERT FORM(AFFIXED, f1, f2, RIGIDLY, t1);
.REFILL